#!/usr/bin/env python
import sys
import struct
import os

from scapy.all import sniff, sendp, hexdump, get_if_list, get_if_hwaddr, bind_layers
from scapy.all import Packet, IPOption
from scapy.all import ShortField, IntField, LongField, BitField, FieldListField, FieldLenField
from scapy.all import Ether, IP, IPv6, TCP, UDP, Raw
from scapy.layers.inet import _IPOption_HDR
from scapy.fields import *


class IPOption_MRI(IPOption):
    name = "MRI"
    option = 31
    fields_desc = [ _IPOption_HDR,
                    FieldLenField("length", None, fmt="B",
                                  length_of="swids",
                                  adjust=lambda pkt,l:l+4),
                    ShortField("count", 0),
                    FieldListField("swids",
                                   [],
                                   IntField("", 0),
                                   length_from=lambda pkt:pkt.count*4) ]
class SourceRoute(Packet):
    fields_desc = [
        BitField("bos", 0, 1),
        BitField("port", 0, 15)
    ]
class SourceRoutingTail(Packet):
   fields_desc = [ XShortField("etherType", 0x800)]

bind_layers(Ether, SourceRoute, type=0x1234)
bind_layers(SourceRoute, SourceRoute, bos=0)
bind_layers(SourceRoute, IP, bos=1)
bind_layers(SourceRoute, IPv6, bos=1)

def get_if():
    ifs = get_if_list()
    iface = next((i for i in ifs if "eth0" in i), None)
    if not iface:
        print("Cannot find eth0 interface")
        exit(1)
    return iface

def handle_pkt(pkt):
    if Ether in pkt:
        if pkt[Ether].type == 0x1234 and SourceRoute in pkt:
            print("\n=== Received Source Routed Packet ===")
            # 提取源路由路径
            route = []
            sr_layer = pkt[Ether].payload
            while isinstance(sr_layer, SourceRoute):
                route.append(str(sr_layer.port))
                sr_layer = sr_layer.payload

            print(f"Route Path: {' -> '.join(route)}")

            if IPv6 in pkt:
                print(f"IPv6 Packet: {pkt[IPv6].src} -> {pkt[IPv6].dst}")
            elif IP in pkt:
                print(f"IPv4 Packet: {pkt[IP].src} -> {pkt[IP].dst}")

        elif IPv6 in pkt:
            print(f"\n=== Received IPv6 Packet: {pkt[IPv6].src} -> {pkt[IPv6].dst} ===")
        elif IP in pkt:
            print(f"\n=== Received IPv4 Packet: {pkt[IP].src} -> {pkt[IP].dst} ===")

        pkt.show2()
    sys.stdout.flush()

def main():
    iface = get_if()
    print(f"Sniffing on interface {iface}")

    # 捕获所有UDP 4321端口的包和源路由包
    sniff_filter = "(udp and port 4321) or (ether proto 0x1234)"
    sniff(iface=iface, filter=sniff_filter, prn=handle_pkt)

if __name__ == '__main__':
    main()
